/*
 * system3.c: PT System3 specific stuff
 *
 * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
 * Copyright (C) 2001  Stefan Eletzhofer 
 *                               (stefan.eletzhofer@www.eletztrick.de)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ident "$Id: system3.c,v 1.9 2002/01/03 16:07:18 erikm Exp $"

/**********************************************************************
 * includes
 */

#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif

#include <blob/main.h>
#include <blob/arch.h>
#include <blob/errno.h>
#include <blob/error.h>
#include <blob/util.h>
#include <blob/serial.h>
#include <blob/flash.h>
#include <blob/init.h>
#include <blob/command.h>
#include <blob/uucodec.h>
#include <blob/serial.h>

/**********************************************************************
 * defines
 */

/* this will send a cold shiver through erik's spine ... */
#define	ERR( x )		{ ret = x; goto DONE; }

/* more readable IMHO */
#define MEM( x )        (*((u32 *)x))

/**********************************************************************
 * globals
 */

extern blob_status_t blob_status;

/**********************************************************************
 * module globals
 */

/* flash descriptor for System3 flash. */
/* System 3 uses 2xINTEL e28F640 Chips */
static flash_descriptor_t system3_flash_descriptors[] =
{
	{
		size: 2 * 128 * 1024,
		num: 64,
		lockable: 1
	},
	{
		/* NULL block */
	},
};

/**********************************************************************
 * static functions
 */

/*********************************************************************
 * init_system3_flash
 *
 * AUTOR:	SELETZ
 * REVISED:
 *
 * inits system 3 flash driver
 *
 */
static void init_system3_flash_driver(void)
{
	flash_descriptors = system3_flash_descriptors;
	flash_driver = &intel32_flash_driver;
}

__initlist(init_system3_flash_driver, INIT_LEVEL_DRIVER_SELECTION);




static void system3_init_hardware(void)
{
	/* select serial driver */
	serial_driver = &sa11x0_serial_driver;
}

__initlist(system3_init_hardware, INIT_LEVEL_DRIVER_SELECTION);




/*********************************************************************
 * cmd_download_file
 *
 * AUTOR:		SELETZ
 * REVISED:
 *
 * Download a file to arbitary memory location
 *
 */
int cmd_download_file( int argc, char *argv[] )
{
	int		ret		= 0;
	u32		dest	= 0L;
	u32		len	= 0L;

	if ( argc < 3 )				ERR( -EINVAL );

	ret = strtou32( argv[1], &dest );
	if ( ret < 0 )				ERR( -EINVAL );

	ret = strtou32( argv[2], &len );
	if ( ret < 0 )				ERR( -EINVAL );

	if (blob_status.terminalSpeed != blob_status.downloadSpeed) {
		SerialOutputString("Switching to download speed\n");
		SerialOutputString("You have 60 seconds to switch your terminal emulator to the same speed and\n");
		SerialOutputString("start downloading. After that " PACKAGE " will switch back to term speed.\n");
	
		serial_init(blob_status.downloadSpeed);
	} else {
		SerialOutputString("You have 60 seconds to start downloading.\n");
	}

	ret = UUDecode((char *)dest, len);
	if ( ret == len ) {
		SerialOutputString("Received ");
		SerialOutputDec(ret);
		SerialOutputString(" (0x");
		SerialOutputHex(ret);
		SerialOutputString(") bytes.\n");
		ret = 0;
	} else {
		SerialOutputString("error during uudecode\n");
	}
	
	if (blob_status.terminalSpeed != blob_status.downloadSpeed) {
		SerialOutputString("\n(Please switch your terminal emulator back to terminal speed\n");
		serial_init(blob_status.terminalSpeed);
	}

DONE:
	return ret;
}
static char downloadhelp[] = "dlfile destadr filelength\n"
"download file to memory\n";
__commandlist( cmd_download_file, "dlfile", downloadhelp );

/*********************************************************************
 * cmd_flash_write
 *
 * AUTOR:	SELETZ
 * REVISED:
 *
 * Command wrapper for low-level flash write access
 *
 */
static int cmd_flash_write( int argc, char *argv[] )
{
	int ret = 0;
	u32	src	= 0L;
	u32	dest	= 0L;
	u32	len	= 0L;

	if ( argc < 4 )				ERR( -EINVAL );

	ret = strtou32( argv[1], &src );
	if ( ret < 0 )				ERR( -EINVAL );

	ret = strtou32( argv[2], &dest );
	if ( ret < 0 )				ERR( -EINVAL );

	ret = strtou32( argv[3], &len );
	if ( ret < 0 )				ERR( -EINVAL );

	if ( len & (0x3) ) {
		len = (len>>2)  + 1;
	} else {
		len = len>>2;
	}

	_DBGU32( src );
	_DBGU32( dest );
	_DBGU32( len );

	ret = flash_write_region( (u32 *)dest, (u32*)src, len );
DONE:
	return ret;
}
static char flashwritehelp[] = "fwrite srcadr destadr size(bytes)\n"
"flash a memory region\n";
__commandlist( cmd_flash_write, "fwrite", flashwritehelp );

/*********************************************************************
 * cmd_flash_erase
 *
 * AUTOR:	SELETZ
 * REVISED:
 *
 * Command wrapper for low-level flash erasing
 *
 */
static int cmd_flash_erase( int argc, char *argv[] )
{
	int ret = 0;
	u32	dest	= 0L;
	u32	len	= 0L;

	if ( argc < 3 )				ERR( -EINVAL );

	ret = strtou32( argv[1], &dest );
	if ( ret < 0 )				ERR( -EINVAL );

	ret = strtou32( argv[2], &len );
	if ( ret < 0 )				ERR( -EINVAL );

	if ( len & (0x3) ) {
		len = (len>>2)  + 1;
	} else {
		len = len>>2;
	}

	ret = flash_erase_region( (u32 *)dest, len );
DONE:
	return ret;
}
static char flasherasehelp[] = "ferase adr size(bytes)\n"
"erase a flash region\n";
__commandlist( cmd_flash_erase, "ferase", flasherasehelp );
